import { pick, getRandomId } from './helper';

const children = {};

function Form(data) {
  if (this instanceof Form) {
    return Form(data);
  }

  let form = [];

  function set(name, value) {
    form = form.filter(t => t.name !== name);
    form.push({ name, value });
  }

  function append(name, value, filename) {
    form.push({ name, value, filename });
  }

  function keys() {
    return form.map(t => t.name);
  }

  function get(name) {
    const target = form.find(t => t.name === name);
    return target ? target.value : null;
  }

  function getAll(name) {
    return form.filter(t => t.name === name).map(t => t.value);
  }

  function remove(name) {
    form = form.filter(t => t.name !== name);
  }

  function entries() {
    return form.map(t => ({ name: t.name, value: t.value }));
  }

  function has(name) {
    return form.some(t => t.name === name);
  }

  function values() {
    return form.map(t => t.value);
  }

  function toFormData() {
    const d = new FormData();
    form.forEach(({ name, value, filename }) => {
      if (filename) {
        d.append(name, value, filename);
      } else {
        d.append(name, value);
      }
    });
    return d;
  }

  if ((typeof data === 'object' && data) || Array.isArray(data)) {
    Object.keys(data).forEach(name => set(name, data[name]));
  }

  const uuid = getRandomId(16);
  children[uuid] = true;

  return Object.freeze({
    uuid,
    set,
    append,
    keys,
    get,
    getAll,
    delete: remove,
    entries,
    has,
    values,
    toFormData
  });
}

function hasChildOf(some) {
  const uuid = pick('uuid')(some);
  return uuid && !!children[uuid];
}

Object.defineProperty(Form, 'existChildOf', {
  value: hasChildOf,
  writable: false,
  configurable: false
});

export default Form;
